﻿namespace AtfutureCodeMachine
{
    using System;
    using System.IO;
    using System.Net;
    using System.Net.Sockets;
    using System.Text;
    using System.Threading;
    public class WebServer
    {
        private TcpListener mylistener;
        private Thread th;
        //开始兼听端口
        //同时启动一个兼听进程
        public WebServer()
        {
            try
            {
                //开始兼听端口
                //获取本级地址
                IPAddress ip = IPAddress.Parse("127.0.0.1");

                Random ran = new Random();
                
                bool isSuccess = false;
                while (!isSuccess)
                {
                    try
                    {
                        GlobalString.PORT = ran.Next(10000)+50000;
                        //应该随机一个端口
                        mylistener = new TcpListener(ip, GlobalString.PORT);
                        mylistener.Start();

                        isSuccess = true;
                    }
                    catch { }
                }


                //Console.WriteLine("web server running... press ^c to stop...");
                try
                {
                    //同时启动一个兼听进程 ''startlisten''
                    th = new Thread(new ThreadStart(startlisten));
                    th.Start();
                    //ThreadPool.QueueUserWorkItem(new WaitCallback(startlisten), null);
                }
                catch { }
            }
            catch (Exception e)
            {
                Console.WriteLine("兼听端口时发生错误 :" + e.ToString());
            }
        }
        public void Sendheader(string shttpversion, string smimeheader, int itotbytes, string sstatuscode, ref Socket mySocket)
        {
            string sbuffer = "";
            if (smimeheader.Length == 0)
            {
                smimeheader = "text/html; charset=gb2312"; // 默认 text/html
            }
            sbuffer = sbuffer + shttpversion + sstatuscode + "\r\n";
            sbuffer = sbuffer + "Server: atfuture-web-b\r\n";
            sbuffer = sbuffer + "Content-Type: " + smimeheader + "\r\n";
            sbuffer = sbuffer + "accept-ranges: bytes\r\n";
            sbuffer = sbuffer + "Content-Length: " + itotbytes + "\r\n\r\n";
            byte[] bSenddata = Encoding.Default.GetBytes(sbuffer);
            Sendtobrowser(bSenddata, ref mySocket);
            Console.WriteLine("Content-Length: " + itotbytes.ToString());
        }
        void Sendtobrowser(string sdata, ref Socket mySocket)
        {
            Sendtobrowser(Encoding.ASCII.GetBytes(sdata), ref mySocket);
        }
        void Sendtobrowser(byte[] bSenddata, ref Socket mySocket)
        {
            int numbytes = 0;
            try
            {
                if (mySocket.Connected)
                {
                    if ((numbytes = mySocket.Send(bSenddata, bSenddata.Length, 0)) == -1)
                        Console.WriteLine("Socket error cannot Send packet");
                    else
                    {
                        Console.WriteLine("no. of bytes Send {0}", numbytes);
                    }
                }
                else
                    Console.WriteLine("连接失败....");
            }
            catch (Exception e)
            {
                Console.WriteLine("发生错误 : {0} ", e);
            }
        }
        ~WebServer()
        {
            isExit = true;
            Exit();
        }

        bool isExit = false;
        Socket mySocket = null;

        public void startlisten()
        {
            int istartpos = 0;
            string srequest;
            string sdirname;
            string srequestedFile;
            /////////////////////////////////////注意设定你自己的虚拟目录/////////////////////////////////////
            string smywebserverroot = WebProcessing.RootPath;
            //////////////////////////////////////////////////////////////////////////////////////////////////
            string sresponse = "";
            while (!isExit)
            {
                try
                {
                    //接收新连接
                    mySocket = mylistener.AcceptSocket();
                }
                catch { }
                if (mySocket.Connected)
                {
                    byte[] breceive = new byte[1024];
                    int i = mySocket.Receive(breceive, breceive.Length, 0);
                    //转换成字符串类型
                    string sbuffer = Encoding.ASCII.GetString(breceive);
                    //只处理"get"请求类型
                    if (sbuffer.Substring(0, 3).ToLower() != "get")
                    {
                        Console.WriteLine("只处理get请求类型..");
                        mySocket.Close();
                        return;
                    }
                    // 查找 "http" 的位置
                    istartpos = sbuffer.ToLower().IndexOf("http",1);
                    //"GET /1.html?aa=33 HTTP/1.1\r\nAccept: image/jpeg, application/x-ms-application, image/gif, application/xaml+xml, image/pjpeg, application/x-ms-xbap, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/QVOD, application/QVOD, application/x-shockwave-flash, */*\r\nAccept-Language: zh-CN\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.2; .NET4.0C; .NET4.0E; 56flvplayer 1.0; Tablet PC 2.0)\r\nAccept-Encoding: gzip, deflate\r\nHost: 127.0.0.1:58462\r\nConnection: Keep-Alive\r\n\r\n\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
                    //
                    string shttpversion = sbuffer.Substring(istartpos, 8);
                    
                    // 得到请求类型和文件目录文件名
                    srequest = sbuffer.Substring(0, istartpos - 1);
                    srequest.Replace("\\", "/");
                    //如果结尾不是文件名也不是以"/"结尾则加"/"
                    if ((srequest.IndexOf(".") < 1) && (!srequest.EndsWith("/")))
                    {
                        srequest = srequest + "/";
                    }
                    //得带请求文件名
                    istartpos = srequest.LastIndexOf("/") + 1;
                    srequestedFile = srequest.Substring(istartpos);
                    
                    //得到请求文件目录
                    sdirname = srequest.Substring(srequest.IndexOf("/"), srequest.LastIndexOf("/") - 3);

                    string strFilePath = srequest.Substring(4);

                    if (srequestedFile.Length == 0)
                    {
                        // 取得请求文件名
                        srequestedFile = "index.htm";
                    }
                    /////////////////////////////////////////////////////////////////////
                    // 取得请求文件类型（设定为text/html）
                    /////////////////////////////////////////////////////////////////////
                    string smimetype = "text/html; charset=gb2312";
                    //if(!File.Exists(sphysicalFilepath))
                    //图片处理方式
                    if (sdirname.ToLower().IndexOf("/image/") == -1)
                    {
                        string content = "";

                        //处理业务
                        var arr = strFilePath.Split('?');
                        object args = null;
                        if (arr.Length > 1) args = arr[1];
                        content = ViewTemplate.Parse(arr[0], args);

                        byte[] bytes = Encoding.Default.GetBytes(content);
                        Sendheader(shttpversion, smimetype, bytes.Length, " 200 OK", ref mySocket);
                        Sendtobrowser(bytes, ref mySocket);
                    }
                    else
                    {
                        //得到图片类型
                        smimetype = "image/" + srequestedFile.Substring(srequestedFile.LastIndexOf(".") + 1);

                        int itotbytes = 0;
                        sresponse = "";
                        FileStream fs = new FileStream(
                            WebProcessing.RootPath + strFilePath,
                            FileMode.Open,
                            FileAccess.Read,
                            FileShare.Read);

                        BinaryReader reader = new BinaryReader(fs);
                        byte[] bytes = new byte[fs.Length];
                        int read;
                        while ((read = reader.Read(bytes, 0, bytes.Length)) != 0)
                        {
                            sresponse = sresponse + Encoding.ASCII.GetString(bytes, 0, read);
                            itotbytes = itotbytes + read;
                        }
                        reader.Close();
                        fs.Close();
                        Sendheader(shttpversion, smimetype, itotbytes, " 200 OK", ref mySocket);
                        Sendtobrowser(bytes, ref mySocket);
                    }
                    /*
                    serrormessage = "<h2>404 error! File does not exists...</h2>";
                    Sendheader(shttpversion, "", serrormessage.Length, " 404 not found", ref mySocket);
                    Sendtobrowser(serrormessage, ref mySocket);
                    Console.WriteLine(sformattedmessage);
                    */

                    mySocket.Close();
                }
            }
        }

        /// <summary>
        /// 退出
        /// </summary>
        internal void Exit()
        {
            isExit = true;
            try
            {
                if (mySocket != null)
                {
                    mySocket.Close();
                    mySocket = null;
                }

                mylistener.Stop();

                th.Abort();
            }
            catch (Exception e)
            {
                
            }

        }
    }
}